package reflect_utils

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"unsafe"
)

// FillDefaultField 填充结构体默认值属性，通过为属性default标签设置默认值，支持复杂嵌套结构
// 仅针对配置文件读取后的填充默认值，不负责创建属性。
// 目前仅用于填充配置结构的默认值(复合类型仅支持slice与struct)
// @in 输入结构体
func FillDefaultField(in any) error {
	return fillDefaultField(in, nil)
}

// fillDefaultField
// in 输入结构体 ， entityAddr 起始地址（初始调用传 nil ）
func fillDefaultField(in any, entityAddr unsafe.Pointer) error {
	if in == nil {
		return errors.New("非法空对象")
	}

	val := reflect.ValueOf(in)
	typ := reflect.TypeOf(in)

	if val.IsNil() {
		return errors.New("未初始化")
	}

	// 获取结构体初始偏移量
	if entityAddr == nil {
		entityAddr = val.UnsafePointer()
	}
	// 若是指针类型，直接获取到真实的对象
	for typ.Kind() == reflect.Ptr {
		val = val.Elem()
		typ = typ.Elem()
	}

	kind := typ.Kind()
	if kind != reflect.Struct {
		return errors.New("错误类型")
	}

	numField := typ.NumField()

	for i := 0; i < numField; i++ {
		structField := typ.Field(i)
		structFieldVal := val.Field(i)
		structFieldKind := structField.Type.Kind()
		//structFieldTag := structField.Tag

		// 如果没有标签，则跳过属性（没有标签则表示不需要通过文件序列化，自然也就不需要默认值）
		//if structFieldTag == "" {
		//	continue
		//}

		// 结构体的属性如果是 struct 或者 *struct ， 需要递归处理
		if structFieldKind == reflect.Struct ||
			(structFieldKind == reflect.Ptr && structField.Type.Elem().Kind() == reflect.Struct) {

			// 通过地址推导计算， 获取到当前的结构体属性（处于内存中的真实位置）
			/* 注意，结构体递归处理不可以使用reflect.Value() */
			realfield := reflect.NewAt(structField.Type, unsafe.Pointer(uintptr(entityAddr)+structField.Offset))
			realType := realfield.Elem().Type().Kind()
			if realType == reflect.Ptr {
				/*
					表示此struct上当前属性的值是指针（如 u *User 的结构，realfield 获取到的是二级指针 **User ，需要再获取一级指针），
					realType 如果是指针，需要通过elem()获取一级指针才可以修改值；
							 如果非指针，则不需要取elem
					u *User ->  【realType == reflect.Ptr 】     realfield.Elem().Interface()
					u User ->   【realType == reflect.Struct 】  realfield.Interface()
				*/
				realfield = realfield.Elem()
			}

			// 嵌套struct递归，偏移量为当前属性的偏移量
			fillDefaultField(realfield.Interface(), unsafe.Pointer(uintptr(entityAddr)+structField.Offset))

		} else if structFieldKind == reflect.Array || structFieldKind == reflect.Slice {
			// 结构体的属性如果是 []Struct 或者 []*Struct ， 需要遍历递归

			// 获取slice初始偏移量，通过地址推导 逐个获取变量执行递归
			firstAddr := unsafe.Pointer(structFieldVal.Pointer())
			for j := 0; j < structFieldVal.Len(); j++ {
				// 拿到slice的第j个节点对应的结构（ 非Elem() )
				sliceEle := structFieldVal.Index(j)

				size := unsafe.Sizeof(sliceEle.Type())

				// 获取到真实第j个值的地址对象( [j]User 或者 [j]*User )
				realfield := reflect.NewAt(sliceEle.Type(), unsafe.Pointer(uintptr(firstAddr)+uintptr(j)*size))

				/* u []*User 与 u []User 的处理 */
				realType := realfield.Elem().Type().Kind()
				if realType == reflect.Pointer {
					realfield = realfield.Elem()
				}

				// 判断当前值的类型是否为struct 或者 *Struct
				if sliceEle.Type().Kind() == reflect.Struct || sliceEle.Type().Kind() == reflect.Ptr {
					fillDefaultField(realfield.Interface(), unsafe.Pointer(uintptr(firstAddr)+uintptr(j)*size))
				} else {
					// TODO 常规 []int \ []string 等暂时不做处理
				}
			}
		} else {
			// 如果结构体属性为常规类型，则查找默认值对比赋值
			newVal, err := checkAndGetDefaultVal(structFieldVal.Interface(), structField)
			if nil != err {
				continue
			} else {
				if structFieldVal.CanSet() {
					structFieldVal.Set(reflect.ValueOf(newVal))
					fmt.Println(in)
				}
			}

		}
	}

	return nil
}

// 判断并获取默认值
func checkAndGetDefaultVal(in any, sfd reflect.StructField) (any, error) {
	val := reflect.ValueOf(in)

	// 属性存在default标签 && 属性的值非类型零值  才需要修改
	// 否则不需要修改
	if !hasDefaultTag(sfd) || !isZeroOfUnderlyingType(in) {
		return nil, errors.New("不需要修改")
	}

	var tranVal any
	var kind = reflect.Indirect(val).Kind()
	var defaultVal = sfd.Tag.Get("default")

	// 判断属性类型并转化默认值
	switch kind {
	case reflect.Bool:
		tranVal, _ = strconv.ParseBool(defaultVal)

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		tranVal, _ = strconv.ParseInt(defaultVal, 0, 64)

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		tranVal, _ = strconv.ParseUint(defaultVal, 0, 64)

	case reflect.Float32, reflect.Float64:
		tranVal, _ = strconv.ParseFloat(defaultVal, 64)

	case reflect.String:
		tranVal = defaultVal

	default:
		return nil, errors.New("没有匹配的类型")

	}
	return tranVal, nil
}

// 判断结构体属性Tag是否存在默认值 default
func hasDefaultTag(sfd reflect.StructField) bool {
	tag := sfd.Tag
	return tag.Get("default") != ""
}

// 判断当前类型的值是否与类型零值相等
func isZeroOfUnderlyingType(x any) bool {
	zero := reflect.Zero(reflect.TypeOf(x)).Interface()
	res := reflect.DeepEqual(x, zero)
	return res
	//return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}
